import React from 'react';
import { Modal } from '@components/index';

enum EAction {
    OPEN = "OPEN",
    CLOSE = "CLOSE"
}

/**
 * @typedef { Object } IConfirmationModalBody - Интерфейс для содержимого модального окна.
 * @property { React.ReactNode } title - Заголовок модального окна.
 * @property { React.ReactNode } content - Содержимое модального окна.
 * @property { React.ReactNode } actions - Действия модального окна, например кнопки.
 */
export interface IConfirmationModalBody {
    title?: React.ReactNode;
    content?: React.ReactNode;
    actions?: React.ReactNode;
}

/**
 * @typedef { Object } IConfirmationModalState - Интерфейс для 
 * @property {boolean} isOpen - Статус открытия модального окна.
 * @property { IConfirmationModalBody | null } modalBody - Тело модального окна с данными.
 */
interface IConfirmationModalState {
    isOpen: boolean;
    modalBody: IConfirmationModalBody | null;
}

/**
 * @typedef { Object } TOpenAction - Тип для открытия модального окна.
 * @property { EAction.OPEN } type - Тип действия для открытия модального окна.
 * @property { IConfirmationModalBody } payload - Данные для модального окна.
 */
type TOpenAction = {
    type: EAction.OPEN,
    payload: IConfirmationModalBody
};

/**
 * @typedef { Object } TCloseAction - Тип для закрытия модального окна.
 * @property { EAction.CLOSE } type - Тип действия для закрытия модального окна.
 */
type TCloseAction = {
    type: EAction.CLOSE
}

/**
 * @typedef { TOpenAction | TCloseAction } TConfirmationModalAction - Типы действий
 *  для модального окна.
 */
type TConfirmationModalAction = TOpenAction | TCloseAction;

/**
 * @typedef {Object} TConfirmationModalContext - Тип для контекста модального окна.
 * @property { (IConfirmationModalBody) => void } open - Функция для открытия модального окна.
 * @property { () => void} close - Функция для закрытия модального окна.
 */
type TConfirmationModalContext = {
    open: (payload: IConfirmationModalBody) => void;
    close: () => void;
}

/**
 * Создает контекст для управления модальным окном подтверждения.
 */
const ConfirmationModalContext = React.createContext<TConfirmationModalContext>(
    {
        open: () => { },
        close: () => { }
    }
);

/**
 * Редьюсер для обработки состояний и действий модального окна подтверждения.
 * 
 * @param { IConfirmationModalState } state - Текущее состояние модального окна.
 * @param { TConfirmationModalAction } action - Действие, которое нужно выполнить.
 * @returns { IConfirmationModalState } - Новое состояние модального окна.
 */
const confirmationModalReducer = (state: IConfirmationModalState, actions: TConfirmationModalAction): IConfirmationModalState => {

    switch (actions.type) {
        case EAction.OPEN:
            return {
                isOpen: true,
                modalBody: {
                    ...actions.payload
                }
            };
        case EAction.CLOSE:
            return {
                isOpen: false,
                modalBody: null
            };
        default:
            return state;
    }
}

const defaultState: IConfirmationModalState = {
    isOpen: false,
    modalBody: null
}

/**
 * @function ConfirmationModalProvider - Провайдер контекста для модального окна подтверждения.
 * Оборачивает дочерние компоненты и предоставляет функции open и close.
 * 
 * @param { Object } props - Пропсы компонента.
 * @param { React.PropsWithChildren } props.children - Дочерние компоненты.
 * @returns { React.ReactNode } - Элемент провайдера контекста.
 */
const ConfirmationModalProvider: React.FC<React.PropsWithChildren> = ({children}) => {

    const [state, dispatch] = React.useReducer(confirmationModalReducer, defaultState);

    const open = (payload: IConfirmationModalBody) => {
        dispatch({ type: EAction.OPEN, payload });
    };

    const close = () => {
        dispatch({ type: EAction.CLOSE });
    };

    const contextValue = React.useMemo(() => ({ open, close }), [open, close]);

    return (
        <ConfirmationModalContext.Provider value={contextValue}>
            {
                (state.isOpen && state.modalBody) && (
                    <Modal
                        dimension="sm"
                        closeOnOutsideClick
                        displayCloseIcon={false}
                        showModal={state.isOpen}
                        onClose={close}
                        className='modal'
                    >
                        {
                            state.modalBody.title && (
                                <Modal.Title>
                                    {state.modalBody.title}
                                </Modal.Title>
                            )
                        }
                        {
                            state.modalBody.content && (
                                <Modal.Content>
                                {state.modalBody.content}
                                </Modal.Content>
                            )
                        }
                        {
                            state.modalBody.actions && (
                                <Modal.Actions>
                                    {state.modalBody.actions}
                                </Modal.Actions>
                            )
                        }
                    </Modal>
                )
            }
            {children}
        </ConfirmationModalContext.Provider>
    );
};

/**
 * Хук для использования контекста модального окна подтверждения.
 * 
 * @returns { TConfirmationModalContext } - Контекст модального окна.
 */
export const useConfirmationModal = () => {
    const confirmationModalContext = React.useContext(ConfirmationModalContext);
    return confirmationModalContext;
}

export default ConfirmationModalProvider;